package com.luxiu.extensionlib.adapter

import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import java.util.Collections

interface OnGroupClickListener {
    fun onGroupClick(groupId: Int, toExpanded: Boolean): Boolean
}

interface OnGroupClickToToggleListener {
    fun onToggleToClick(groupId: Int): Boolean
}

interface ExpandCollapseListener {

    /**
     * 当组展开时
     * group是展开的组
     */
    fun onGroupExpanded(groupId: Int, parent: BaseParentItem<*>)

    /**
     * 当组折叠时
     * group是折叠的组
     */
    fun onGroupCollapsed(groupId: Int, parent: BaseParentItem<*>)
}

abstract class BaseBilayerAdapter<P : BaseBilayerInterface, C : BaseBilayerInterface, GVH : BaseParentViewHolder, CVH : ChildViewHolder> :
    RecyclerView.Adapter<RecyclerView.ViewHolder>(),
    OnGroupClickToToggleListener {

    private var groupClickListener: OnGroupClickListener? = null
    private var expandCollapseListener: ExpandCollapseListener? = null

    private val parents = Collections.synchronizedList(mutableListOf<BaseParentItem<P>>())
    private val children = Collections.synchronizedList(mutableListOf<BaseChildItem<C>>())
    private val displayItems = Collections.synchronizedList(mutableListOf<BaseBilayerItem<*>>())
    private val expandedGroups = mutableSetOf<Int>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            BilayerType.GROUP -> {
                val gvh = onCreateParentViewHolder(parent, viewType)
                gvh.setOnGroupClickToToggleListener(this)
                gvh
            }

            BilayerType.CHILD -> onCreateChildViewHolder(parent, viewType)
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = displayItems[position]
        when (item.itemType) {
            BilayerType.GROUP -> {
                val parentItem = item as BaseParentItem<P>
                val groupId = parentItem.value.getId()
                holder.itemView.setOnClickListener {
                    val isExpanded =
                        (holder as BaseParentViewHolder).listenerInternal!!.onToggleToClick(groupId)
                    if (parentItem.isCollapsible) {
                        holder.listener?.onGroupClick(groupId, isExpanded)
                    }
                }
                onBindParentViewHolder(holder as GVH, position, item)
            }

            BilayerType.CHILD -> {
                onBindChildViewHolder(holder as CVH, position, item as BaseChildItem<C>)
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        return displayItems[position].itemType
    }

    override fun getItemCount(): Int = displayItems.size


    override fun onToggleToClick(groupId: Int): Boolean {
        var isExpanded = true
        synchronized(displayItems) {
            val position = findGroupPositionById(groupId)
            if (position == -1) return false

            if (displayItems[position].itemType == BilayerType.GROUP) {
                val parentItem = displayItems[position] as BaseParentItem<*>
                parentItem.isExpanded = !parentItem.isExpanded
                isExpanded = parentItem.isExpanded

                if (!parentItem.isCollapsible) return true

                // 更新展开状态集合
                if (isExpanded) {
                    expandedGroups.add(groupId)
                } else {
                    expandedGroups.remove(groupId)
                }

                if (isExpanded) {
                    // 展开操作
                    val childrenToAdd = children.filter { it.value.getGroupId() == groupId }
                    if (childrenToAdd.isNotEmpty()) {
                        displayItems.addAll(position + 1, childrenToAdd)
                        notifyItemRangeInserted(position + 1, childrenToAdd.size)
                        expandCollapseListener?.onGroupExpanded(groupId, parentItem)
                    }
                } else {
                    val itemsToRemove = mutableListOf<BaseBilayerItem<*>>()
                    var index = position + 1
                    while (index < displayItems.size && displayItems[index].itemType == BilayerType.CHILD) {
                        val childItem = displayItems[index] as BaseChildItem<*>
                        if (childItem.value.getGroupId() == groupId) {
                            itemsToRemove.add(displayItems[index])
                            index++
                        } else {
                            break
                        }
                    }
                    if (itemsToRemove.isNotEmpty()) {
                        val removeCount = itemsToRemove.size
                        displayItems.removeAll(itemsToRemove)
                        notifyItemRangeRemoved(position + 1, removeCount)
                        expandCollapseListener?.onGroupCollapsed(groupId, parentItem)
                    }
                }
                notifyItemChanged(position)
            }
        }
        return isExpanded
    }

    // 在数据更新时保持展开状态
    private fun updateParentInternal(newParents: List<BaseParentItem<P>>) {
        // 保存当前展开状态
        val currentExpandedStates = parents.associate { it.value.getId() to it.isExpanded }

        parents.clear()
        parents.addAll(filterParentList(newParents))

        // 恢复展开状态，确保不可折叠组始终展开
        parents.forEach { group ->
            val groupId = group.value.getId()

            // 如果组不可折叠，强制设置为展开
            if (!group.isCollapsible) {
                group.isExpanded = true
                expandedGroups.add(groupId)
            } else {
                group.isExpanded = when {
                    currentExpandedStates.containsKey(groupId) -> currentExpandedStates[groupId]!!
                    groupId in expandedGroups -> true
                    else -> true // 默认展开
                }

                // 确保expandedGroups与当前状态同步
                if (group.isExpanded) {
                    expandedGroups.add(groupId)
                } else {
                    expandedGroups.remove(groupId)
                }
            }
        }
    }

    //toCollapse：true 表示展开，false 表示折叠
    fun doExpandOrCollapse(groupId: Int, toCollapse: Boolean) {
        if (toCollapse) collapseGroup(groupId) else expandGroup(groupId)
    }

    fun doExpandOrCollapseAll(toCollapse: Boolean) {
        if (toCollapse) collapseAll() else expandAll()
    }

    fun expandGroup(groupId: Int) {
        onToggleToClick(groupId)
    }

    fun collapseGroup(groupId: Int) {
        val position = findGroupPositionById(groupId)
        if (position != -1) {
            val parentItem = displayItems[position] as? BaseParentItem<*> ?: return
            if (parentItem.isExpanded) {
                onToggleToClick(groupId)
            }
        }
    }

    fun expandAll() {
        parents.forEach { group ->
            if (!group.isExpanded) {
                onToggleToClick(group.value.getId())
            }
        }
    }

    fun collapseAll() {
        parents.forEach { group ->
            if (group.isExpanded) {
                onToggleToClick(group.value.getId())
            }
        }
    }

    fun setGroupCollapsible(groupId: Int, collapsible: Boolean) {
        parents.forEach {
            if (it.value.getId() == groupId) {
                it.isCollapsible = collapsible
            }
        }
        doExpandOrCollapse(groupId, collapsible)
    }

    fun setGroupCollapsibleAll(collapsible: Boolean) {
        parents.forEach {
            it.isCollapsible = collapsible
        }
        doExpandOrCollapseAll(collapsible)
    }

    private fun findGroupPositionById(groupId: Int): Int {
        synchronized(displayItems) {
            for (i in displayItems.indices) {
                val item = displayItems[i]
                if (item.itemType == BilayerType.GROUP && item.value.getId() == groupId) {
                    return i
                }
            }
        }
        return -1
    }

    fun updateParent(newParents: List<BaseParentItem<P>>) {
        synchronized(displayItems) {
            val oldDisplayItems = ArrayList(displayItems)
            updateParentInternal(newParents)
            rebuildDisplayItems()
            val diffResult =
                DiffUtil.calculateDiff(BilayerDiffCallBack(displayItems, oldDisplayItems))
            diffResult.dispatchUpdatesTo(this)
        }
    }

    fun updateChild(newChildren: List<BaseChildItem<C>>) {
        synchronized(displayItems) {
            val oldDisplayItems = ArrayList(displayItems)
            updateChildInternal(newChildren)
            rebuildDisplayItems()
            val diffResult =
                DiffUtil.calculateDiff(BilayerDiffCallBack(displayItems, oldDisplayItems))
            diffResult.dispatchUpdatesTo(this)
        }
    }

    private fun updateChildInternal(newChildren: List<BaseChildItem<C>>) {
        children.clear()
        children.addAll(filterChildList(newChildren))
    }

    open fun filterChildList(newChildren: List<BaseChildItem<C>>): List<BaseChildItem<C>> {
        return newChildren
    }

    open fun filterParentList(newParents: List<BaseParentItem<P>>): List<BaseParentItem<P>> {
        return newParents
    }

    private fun rebuildDisplayItems() {
        displayItems.clear()
        parents.forEach { group ->
            displayItems.add(group)
            // 关键修改：不可折叠组始终显示子项
            val shouldShowChildren = group.isExpanded || !group.isCollapsible
            if (shouldShowChildren) {
                children.filter { it.value.getGroupId() == group.value.getId() }
                    .forEach { displayItems.add(it) }
            }
        }
    }

    fun getChildCount(parentId: Int): Int {
        return children.filter { it.value.getGroupId() == parentId }.size
    }

    /**
     * 如果是group，返回第几个group
     * 如果是child，返回是group的第几个child
     */
    fun getGroupIndexByPosition(position: Int): Int {
        if (position < 0 || position >= displayItems.size) {
            return -1
        }
        val item = displayItems[position]
        return when (item.itemType) {
            BilayerType.GROUP -> {
                var groupCount = 0
                for (i in 0..position) {
                    if (displayItems[i].itemType == BilayerType.GROUP) {
                        groupCount++
                    }
                }
                groupCount - 1 // 转换为0-based索引
            }

            BilayerType.CHILD -> {
                var groupPosition = position - 1
                while (groupPosition >= 0 && displayItems[groupPosition].itemType != BilayerType.GROUP) {
                    groupPosition--
                }
                if (groupPosition < 0) {
                    return -1
                }
                return position - groupPosition - 1
            }

            else -> -1
        }
    }

    abstract fun onCreateParentViewHolder(parent: ViewGroup, viewType: Int): GVH

    abstract fun onBindParentViewHolder(holder: GVH, position: Int, parentItem: BaseParentItem<P>)

    abstract fun onCreateChildViewHolder(parent: ViewGroup, viewType: Int): CVH

    abstract fun onBindChildViewHolder(holder: CVH, position: Int, childItem: BaseChildItem<C>)

    fun setOnGroupClickListener(listener: OnGroupClickListener) {
        groupClickListener = listener
    }

    fun setOnGroupExpandCollapseListener(listener: ExpandCollapseListener) {
        expandCollapseListener = listener
    }
}

abstract class BaseParentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    var listener: OnGroupClickListener? = null
    var listenerInternal: OnGroupClickToToggleListener? = null

    fun setOnGroupClickToToggleListener(listener: OnGroupClickToToggleListener) {
        this.listenerInternal = listener
    }

    fun setOnGroupClickListener(listener: OnGroupClickListener?) {
        this.listener = listener
    }
}

open class ChildViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!)

interface BaseBilayerItem<T : BaseBilayerInterface> {
    var value: T
    var itemType: Int
    fun isSameItem(other: BaseBilayerItem<*>): Boolean
    fun isSameContent(other: BaseBilayerItem<*>): Boolean
}

interface BaseBilayerInterface {
    fun isSame(other: BaseBilayerInterface): Boolean
    fun getId(): Int
    fun getGroupId(): Int
    override fun toString(): String
}

abstract class BaseParentItem<P : BaseBilayerInterface>(
    override var value: P,
    var isExpanded: Boolean = true,
    override var itemType: Int = BilayerType.GROUP,
    var isCollapsible: Boolean = true
) : BaseBilayerItem<P> {
    override fun toString(): String {
        return "id = ${value.getId()}, value = $value"
    }

    override fun isSameItem(other: BaseBilayerItem<*>): Boolean {
        return other.itemType == BilayerType.GROUP && this.value.getId() == other.value.getId()
    }

    override fun isSameContent(other: BaseBilayerItem<*>): Boolean {
        return other.itemType == BilayerType.GROUP && (other as BaseParentItem).isExpanded == this.isExpanded &&
                this.isCollapsible == other.isCollapsible && this.value.isSame(other.value)
    }
}

abstract class BaseChildItem<C : BaseBilayerInterface>(
    override var value: C,
    override var itemType: Int = BilayerType.CHILD,
) : BaseBilayerItem<C> {
    override fun toString(): String {
        return "id = ${value.getId()}, child = $value"
    }

    override fun isSameItem(other: BaseBilayerItem<*>): Boolean {
        return other.itemType == BilayerType.CHILD && this.value.getId() == other.value.getId() && this.value.getGroupId() == other.value.getGroupId()
    }

    override fun isSameContent(other: BaseBilayerItem<*>): Boolean {
        return other.itemType == BilayerType.CHILD && this.value.isSame(other.value)
    }
}

class BilayerType {
    companion object {
        val CHILD: Int = 1
        val GROUP: Int = 2
    }
}

class BilayerDiffCallBack(
    private val newList: List<BaseBilayerItem<*>>,
    private val oldList: List<BaseBilayerItem<*>>,
) : DiffUtil.Callback() {
    override fun getOldListSize(): Int = oldList.size

    override fun getNewListSize(): Int = newList.size

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        val oldItem = oldList[oldItemPosition]
        val newItem = newList[newItemPosition]
        return oldItem.isSameItem(newItem)
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        val oldItem = oldList[oldItemPosition]
        val newItem = newList[newItemPosition]
        return oldItem.isSameItem(newItem) && oldItem.value.isSame(newItem.value)
    }
}